home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Snippets / QuickDraw / CalcCMask & CalcMask / Source / CalcCMask & CalcMask.c
Encoding:
C/C++ Source or Header  |  1996-09-17  |  6.9 KB  |  255 lines  |  [TEXT/CWIE]

  1. /****************************************************************************/
  2. /*                                                                            */
  3. /*    Application:    CalcCMask & CalcMask                                    */
  4. /*                                                                            */
  5. /*    Description:    This snippet shows how to use both CalcCMask or            */
  6. /*                    CalcMask to create a mask given a source bitmap            */
  7. /*                    image.  As decribed on pages IV-24 and V-72 of            */
  8. /*                    Inside Mac, the two routines compute a destination        */
  9. /*                    bitmap image with 1's only in the pixels where            */
  10. /*                    paint can not leak from any of the outer edges.            */
  11. /*                    This is similar to the lasso tool found in many            */
  12. /*                    drawing apps.                                            */
  13. /*                                                                            */
  14. /*    File:            CalcCMask & CalcMask.π                                    */
  15. /*                    CalcCMask & CalcMask.c                                    */
  16. /*                    CalcCMask & CalcMask.π.rsrc                                */
  17. /*                                                                            */
  18. /*    Programmer:        Edgar Lee                                                */
  19. /*    Organization:    Apple Computer, Inc.                                    */
  20. /*    Department:        Developer Technical Support, DTS                        */
  21. /*    Language:        C (Think C version 5.0.1)                                */
  22. /*    Date Created:    2-26-92                                                    */
  23. /*                                                                            */
  24. /****************************************************************************/
  25.  
  26. #include <Dialogs.h>
  27. #include <Fonts.h>
  28. #include <QDOffscreen.h>
  29. #include <Resources.h>
  30. /* Constant Declarations */
  31.  
  32. #define    WWIDTH        176
  33. #define    WHEIGHT        106
  34.  
  35. #define WLEFT        (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
  36. #define WTOP        (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
  37.  
  38. /* Global Variable Definitions */
  39.  
  40. WindowPtr    gWindow;
  41.  
  42. void initMac();
  43. void createWindow();
  44. void doCalcCMaskExample();
  45.  
  46. void DisposeGrafPort();
  47. GrafPtr CreateGrafPort();
  48.  
  49. void doEventLoop();
  50.  
  51. void main(void)
  52. {
  53.     initMac();
  54.     
  55.     createWindow();
  56.     
  57.     doEventLoop();
  58. }
  59.  
  60. void initMac()
  61. {
  62.     MaxApplZone();
  63.     
  64.     InitGraf( &qd.thePort );
  65.     InitFonts();
  66.     InitWindows();
  67.     InitMenus();
  68.     TEInit();
  69.     InitDialogs( nil );
  70.     InitCursor();
  71.     FlushEvents( 0, everyEvent );
  72. }
  73.  
  74. void createWindow()
  75. {
  76.     Rect rect;
  77.     
  78.     SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  79.     
  80.     gWindow = NewCWindow( 0L, &rect, "\pCalc-C-Mask", true, documentProc,
  81.                             (WindowPtr)-1L, true, 0L );
  82.                             
  83.     SetPort( gWindow );
  84. }
  85.  
  86. #define    COLOR_VERSION
  87.  
  88. void doCalcCMaskExample()
  89. {
  90.     PicHandle    pict;                /* B/W Pict used to create mask. */
  91.     GWorldPtr    gworld;                /* Gworld used for CopyMask source. */
  92.     GrafPtr     mask;                /* Mask created by CalcCMask. */
  93.     GrafPtr        sourceForMask;        /* Bitmap of pict image used for creating mask. */
  94.     RGBColor    seedColor;            /* Color used to determine the mask. */
  95.     Rect        rect;                /* Bounding rect of mask and source. */
  96.     CGrafPtr    currentPort;        /* Saved CGrafPtr for later restore. */
  97.     GDHandle    currentDevice;        /* Saved device for later restore. */
  98.     
  99.     /* Load the pict resource to be used for the mask. */
  100.     pict = (PicHandle)GetResource( 'PICT', 128 );
  101.     
  102.     /* Define the bounding rect for the source and mask bitmap. */
  103.     rect = (**pict).picFrame;
  104.     OffsetRect( &rect, -rect.left, -rect.top );
  105.     
  106.     /* Allocate the source bitmap for which the mask will be created from. */
  107.     sourceForMask = CreateGrafPort( &rect );
  108.     
  109.     /* Create the source bitmap's image by using the pict. */
  110.     SetPort( sourceForMask );
  111.     DrawPicture( pict, &rect );
  112.     SetPort( gWindow );
  113.     
  114.     /* Release the memory used by the pict. */
  115.     ReleaseResource( (Handle)pict );
  116.  
  117.     /* Create a gworld of a blue rectangle for the CopyMask source. */
  118.     GetGWorld( ¤tPort, ¤tDevice );
  119.     NewGWorld( &gworld, 8, &rect, nil, nil, 0 );
  120.     SetPort( (GrafPtr)gworld );
  121.     ForeColor( blueColor );
  122.     PaintRect( &rect );
  123.     SetGWorld( currentPort, currentDevice );
  124.     
  125.     /* Copy the source image to the window to see what the mask was created from. */
  126.     CopyBits( &sourceForMask->portBits, &gWindow->portBits,
  127.                 &sourceForMask->portRect, &rect, srcCopy, nil );
  128.     
  129.     /* Allocate the bitmap for the mask. */
  130.     mask = CreateGrafPort( &sourceForMask->portRect );
  131.  
  132. #ifdef COLOR_VERSION
  133.  
  134.     /* Create a mask from the source bitmap of all colors that match the seedColor. */
  135.     seedColor.red = seedColor.green = seedColor.blue = 0;
  136.     
  137.     CalcCMask( &sourceForMask->portBits, &mask->portBits, &sourceForMask->portRect,
  138.                 &mask->portRect, &seedColor, nil, 0 );
  139.  
  140. #else
  141.  
  142.     CalcMask( &sourceForMask->portBits.baseAddr, &mask->portBits.baseAddr,
  143.                 sourceForMask->portBits.rowBytes, mask->portBits.rowBytes,
  144.                 sourceForMask->portRect.bottom - sourceForMask->portRect.top,
  145.                 sourceForMask->portBits.rowBytes >> 1 );
  146.  
  147. #endif
  148.  
  149.     /* Now draw the blue rectangle with its mask. */
  150.     OffsetRect( &rect, sourceForMask->portRect.right, 0 );
  151.     CopyMask( (BitMap*)&(*gworld).portPixMap, &mask->portBits, &gWindow->portBits,
  152.                 &sourceForMask->portRect, &mask->portRect, &rect );
  153.  
  154.     /* Release the used memory. */
  155.     DisposeGrafPort( sourceForMask );
  156.     DisposeGrafPort( mask );
  157.     DisposeGWorld( gworld );
  158. }
  159.  
  160. GrafPtr CreateGrafPort( bounds )    /* Originally written by Forrest Tanaka. */
  161. Rect *bounds;
  162. {
  163.     GrafPtr    savedPort;        /* Saved GrafPtr for later restore. */
  164.     GrafPtr    newPort;        /* New GrafPort. */
  165.     Rect    localBounds;    /* Local copy of bounds. */
  166.  
  167.     GetPort( &savedPort );
  168.  
  169.     /* Set the top-left corner of bounds to (0,0). */
  170.     localBounds = *bounds;
  171.     OffsetRect( &localBounds, -bounds->left, -bounds->top );
  172.  
  173.     /* Allocate a new GrafPort. */
  174.     newPort = (GrafPtr)NewPtrClear( sizeof( GrafPort ) );
  175.     
  176.     if (newPort != nil)
  177.     {
  178.         /* Initialize the new port and make the current port. */
  179.         OpenPort( newPort );
  180.  
  181.         /* Initialize and allocate the bitmap. */
  182.         newPort->portBits.bounds = localBounds;
  183.           newPort->portBits.rowBytes = ((localBounds.right + 15) >> 4) << 1;
  184.         newPort->portBits.baseAddr =  NewPtrClear( newPort->portBits.rowBytes *
  185.                                                     (long)localBounds.bottom );
  186.         if (newPort->portBits.baseAddr != nil)
  187.         {
  188.             /* Clean up the new port. */
  189.             newPort->portRect = localBounds;
  190.             ClipRect( &localBounds );
  191.             RectRgn( newPort->visRgn, &localBounds );
  192.             EraseRect( &localBounds );
  193.         }
  194.         else
  195.         {
  196.             /* Allocation failed; deallocate the port. */
  197.             ClosePort( newPort );
  198.             DisposePtr( (Ptr)newPort );
  199.             newPort = nil;
  200.         }
  201.     }
  202.     
  203.     SetPort( savedPort );
  204.     return newPort;
  205. }
  206.  
  207. void DisposeGrafPort( doomedPort )        /* Originally written by Forrest Tanaka. */
  208. GrafPtr doomedPort;
  209. {
  210.     ClosePort( doomedPort );
  211.     DisposePtr( doomedPort->portBits.baseAddr );
  212.     DisposePtr( (Ptr)doomedPort );
  213. }
  214.  
  215. void doEventLoop()
  216. {
  217.     EventRecord event;
  218.     WindowPtr   window;
  219.     short       clickArea;
  220.     Rect        screenRect;
  221.  
  222.     for (;;)
  223.     {
  224.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  225.         {
  226.             if (event.what == mouseDown)
  227.             {
  228.                 clickArea = FindWindow( event.where, &window );
  229.                 
  230.                 if (clickArea == inDrag)
  231.                 {
  232.                     screenRect = (**GetGrayRgn()).rgnBBox;
  233.                     DragWindow( window, event.where, &screenRect );
  234.                 }
  235.                 else if (clickArea == inContent)
  236.                 {
  237.                     if (window != FrontWindow())
  238.                         SelectWindow( window );
  239.                 }
  240.                 else if (clickArea == inGoAway)
  241.                     if (TrackGoAway( window, event.where ))
  242.                         return;
  243.             }
  244.             else if (event.what == updateEvt)
  245.             {
  246.                 window = (WindowPtr)event.message;    
  247.                 SetPort( window );
  248.                 
  249.                 BeginUpdate( window );
  250.                 doCalcCMaskExample();
  251.                 EndUpdate( window );
  252.             }
  253.         }
  254.     }
  255. }